<template>
  <div class="app-container">
    <el-card class="box-card">
      <el-form :inline="true" :model="queryForm" class="query-form">
        <el-form-item label="综合查询"
          v-if="tableJson.some((item: { isQuery: boolean, roles: string[] }) => item.isQuery && checkRole(item.roles))">
          <el-input v-model.trim="queryForm.keywords" style="width: 180px" clearable placeholder="请输入关键字" />
        </el-form-item>
        <el-form-item
          v-for="table in tableJson.filter((item: { isSingleQuery: boolean, roles: string[] }) => item.isSingleQuery && checkRole(item.roles))"
          :label="table.remark">
          <!-- 根据类型渲染不同的查询元素 -->
          <template v-if="table.type === 'int' || table.type === 'string' || table.type === 'number'">
            <el-input v-model.trim="queryForm[table.name]" style="width: 180px" clearable
              :placeholder="'请输入' + table.remark" />
          </template>
          <template v-else-if="table.type === 'dict' || table.type === 'dicts'">
            <el-select v-model="queryForm[table.name]" style="width: 180px" clearable :multiple="table.type === 'dicts'"
              :collapse-tags="table.type === 'dicts'" filterable
              :filter-method="(query: string) => { return remoteDict(query, table.associateObject) }"
              :placeholder="'请选择' + table.remark">
              <el-option v-for="item in dictCacheMap.get(table.associateObject)" :key="item.value" :label="item.label"
                :value="item.value" />
            </el-select>
          </template>
          <template v-else-if="table.type === 'object' || table.type === 'objects'">
            <el-select v-model="queryForm[table.name]" style="width: 180px" clearable
              :multiple="table.type === 'objects'" :collapse-tags="table.type === 'objects'" filterable
              :filter-method="(query: string) => { return remoteObject(query, table.associateObject) }"
              :placeholder="'请选择' + table.remark">
              <el-option v-for="item in objectCacheMap.get(table.associateObject)"
                :key="item.code ? item.code : item.id" :label="item.name" :value="item.code ? item.code : item.id" />
            </el-select>
          </template>
          <template v-else-if="table.type === 'date' || table.type === 'timestamp'">
            <el-date-picker v-model="queryForm[table.name]" style="width: 220px" value-format="YYYY-MM-DD"
              type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" />
          </template>
          <template v-else-if="table.type === 'tree'">
            <el-tree-select v-model="queryForm[table.name]" :data="treeCacheMap.get(table.associateObject)"
              :props="{ value: 'id', label: 'name', children: 'children' }" node-key="id" filterable
              :filter-method="(query: string) => { return remoteTree(query, table.associateObject) }"
              :placeholder="'请选择' + table.remark" check-strictly default-expand-all style="width: 180px;" clearable />
          </template>
        </el-form-item>
        <el-form-item>
          <el-button
            v-for="btn in btnJson.filter((item: { position: string, roles: string[] }) => item.position === 'searchBar' && checkRole(item.roles))"
            :key="btn.name" :color="btn.color" @click="handleBtn(btn.btnFunc, null)">{{ btn.name }}</el-button>
        </el-form-item>
      </el-form>

      <el-table :data="list" border stripe style="width: 100%" @selection-change="handleSelectionChange">
        <el-table-column v-if="moduleInfo.isChoice" type="selection" width="55" />
        <el-table-column
          v-for="table in tableJson.filter((item: { showTable: boolean, roles: string[] }) => item.showTable && checkRole(item.roles))"
          :prop="table.name" :label="table.remark" :width="table.columnWidth" :min-width="table.minColumnWidth"
          :fixed="table.isLock" show-overflow-tooltip>
          <template #default="scope">
            <!-- 根据类型渲染不同的表格元素 -->
            <template v-if="table.type === 'int'">
              {{ scope.row[table.name] }}
            </template>
            <template v-else>
              {{ scope.row[table.name] || '--' }}
            </template>
          </template>
        </el-table-column>
        <el-table-column label="操作" :width="moduleInfo.opWidth" fixed="right"
          v-if="btnJson.some((item: { position: string, roles: string[] }) => item.position === 'actionBar' && checkRole(item.roles))">
          <template #default="scope">
            <template
              v-for="btn in btnJson.filter((item: { position: string, roles: string[] }) => item.position === 'actionBar' && checkRole(item.roles))">
              <el-button size="small" :color="btn.color" @click="handleBtn(btn.btnFunc, scope.row)" style="color: #fff">
                {{ btn.name }}
              </el-button>
            </template>
          </template>
        </el-table-column>
      </el-table>

      <div style="height: 18px"></div>

      <el-pagination v-model:current-page="queryForm.pageNum" v-model:page-size="queryForm.pageSize"
        :page-sizes="[10, 50, 100, 500, 1000]" :total="total" layout="total, sizes, prev, pager, next, jumper"
        @size-change="handleSizeChange" @current-change="handleCurrentChange" />
    </el-card>

    <!-- 表单对话框 -->
    <el-dialog v-model="dialogVisible" :title="dialogTitle" :width="moduleInfo.formWidth + 'px'" destroy-on-close>
      <el-form ref="formRef" :model="coreForm" :rules="coreRules" :label-position="moduleInfo.formLabelPosition"
        :label-width="moduleInfo.formLabelWidth + 'px'">
        <el-row :gutter="20">
          <el-col
            v-for="table in tableJson.filter((item: { isAdd: boolean, isEdit: boolean, roles: string[] }) => isFormEdit ? item.isEdit : item.isAdd && checkRole(item.roles))"
            :span="table.rowLayout">
            <el-form-item :label="table.remark" :prop="table.name">
              <!-- 根据类型渲染不同的表单元素 -->
              <template v-if="table.type === 'int' || table.type === 'string' || table.type === 'number'">
                <el-input v-model.trim="coreForm[table.name]" :placeholder="'请输入' + table.remark" />
              </template>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="dialogVisible = false">取消</el-button>
          <el-button type="primary" @click="submitForm">确定</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useRoute } from 'vue-router'
import { useUser } from '@/store/user'
import { ElMessage, ElMessageBox } from 'element-plus'
import {
  apiCoreList,
  apiCoreAdd,
  apiCoreUpdate,
  apiCoreDelete,
} from '@/api/system/core'
import { apiGetModuleInfo } from '@/api/system/module'
import { apiGetDictList } from '@/api/system/dict'

const route = useRoute()
const userStore = useUser()

// 缓存字典
const dictCache = ref<Map<string, any>>(new Map<string, any>())
const dictCacheMap = ref<Map<string, any>>(new Map<string, any>())
// 缓存对象
const objectCache = ref<Map<string, any>>(new Map<string, any>())
const objectCacheMap = ref<Map<string, any>>(new Map<string, any>())
// 缓存树
const treeCache = ref<Map<string, any>>(new Map<string, any>())
const treeCacheMap = ref<Map<string, any>>(new Map<string, any>())

// 模块信息
const moduleInfo = ref<Record<string, any>>({})
// 表格配置
const tableJson = ref<Record<string, any>>([])
// 按钮配置
const btnJson = ref<Record<string, any>>([])
// API配置
const apiJson = ref<Record<string, any>>([])

// 查询表单
const queryForm = ref<Record<string, any>>({
  pageNum: 1,
  pageSize: 10,
})

// 列表与分页
const list = ref<any[]>([])
const total = ref(0)

// 获取列表
const fetchList = async () => {
  const res = await apiCoreList(moduleInfo.value.mid, queryForm.value)
  list.value = res.data?.records || []
  total.value = res.data?.totalRow || 0
}

// 对话框相关
const dialogVisible = ref(false)
const dialogTitle = ref('')
const isFormEdit = ref(false)

// 表单
const initCoreForm = ref<Record<string, any>>({
  sort: 0,
  status: 1,
})
const coreForm = ref<Record<string, any>>({ ...initCoreForm.value })

// 表单验证规则
const coreRules = {}

// 表单引用
const formRef = ref()

// 查询
const handleQuery = () => {
  queryForm.value.pageNum = 1
  fetchList()
}

// 新增
const handleAdd = () => {
  dialogTitle.value = `新增${moduleInfo.value.name}`
  isFormEdit.value = false
  // 重置表单
  Object.assign((coreForm.value = {}), initCoreForm.value)
  dialogVisible.value = true
}

// 编辑
const handleEdit = (row: any) => {
  dialogTitle.value = `编辑${moduleInfo.value.name}`
  isFormEdit.value = true
  // 填充表单数据
  Object.assign(coreForm.value, row)
  dialogVisible.value = true
}

// 删除
const handleDelete = (row: any) => {
  ElMessageBox.confirm(`确定要删除该数据吗？`, '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
  }).then(async () => {
    const res = await apiCoreDelete(moduleInfo.value.mid, { ids: String(row.id) })
    if (res.code == 200) {
      ElMessage.success('删除成功')
      handleQuery()
    } else {
      ElMessage.error(res.message || '删除失败')
    }
  })
}

// 提交表单
const submitForm = () => {
  formRef.value?.validate(async (valid: any) => {
    if (valid) {
      let res: any
      if (isFormEdit.value) {
        res = await apiCoreUpdate(moduleInfo.value.mid, coreForm.value)
      } else {
        res = await apiCoreAdd(moduleInfo.value.mid, coreForm.value)
      }
      if (res.code === 200) {
        ElMessage.success('保存成功')
        dialogVisible.value = false
        handleQuery()
      } else {
        ElMessage.error(res.message || '保存失败')
      }
    }
  })
}

// 分页相关
const handleSizeChange = (val: number) => {
  queryForm.value.pageSize = val
  queryForm.value.pageNum = 1
  fetchList()
}

const handleCurrentChange = (val: number) => {
  queryForm.value.pageNum = val
  fetchList()
}

// 多选
const multipleSelection = ref<[]>([])
const handleSelectionChange = (val: any) => {
  multipleSelection.value = val
}

// 批量删除
const handleBatchDelete = () => {
  if (multipleSelection.value.length == 0) {
    ElMessage.warning('请先选择要删除的数据')
    return
  }
  const ids = multipleSelection.value.map((item: any) => item.id).join(',')
  ElMessageBox.confirm(`确定要删除选中的数据吗？`, '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
  }).then(async () => {
    const res = await apiCoreDelete(moduleInfo.value.mid, { ids: ids })
    if (res.code == 200) {
      ElMessage.success('删除成功')
      handleQuery()
    } else {
      ElMessage.error(res.message || '删除失败')
    }
  })
}

// 批量编辑
const handleBatchEdit = () => {
  if (multipleSelection.value.length == 0) {
    ElMessage.warning('请先选择要编辑的数据')
    return
  }
}

// 执行动态代码
const handleBtn = async (btnFunc: string, row: any) => {
  if (btnFunc) {
    if (btnFunc === 'handleQuery') {
      // 查询列表
      handleQuery()
    } else if (btnFunc === 'handleAdd') {
      // 新增
      handleAdd()
    } else if (btnFunc === 'handleEdit') {
      // 编辑
      handleEdit(row)
    } else if (btnFunc === 'handleDelete') {
      // 删除
      handleDelete(row)
    } else if (btnFunc === 'handleBatchEdit') {
      // 批量编辑
      handleBatchEdit()
    } else if (btnFunc === 'handleBatchDelete') {
      // 批量删除
      handleBatchDelete()
    } else {
      eval(btnFunc)
    }
  }
}

// 远程查询字典
const remoteDict = async (query: string, code: string) => {
  if (!dictCache.value.has(code)) {
    const res = await apiGetDictList(code)
    if (res.code === 200 && res.data) {
      dictCache.value.set(code, res.data)
    }
  }
  const dictList = dictCache.value.get(code) || []
  dictCacheMap.value.set(code, dictList.filter((item: any) => item.label.includes(query)))
}

// 远程查询对象
const remoteObject = async (query: string, associateObject: string) => {
  console.log(query, associateObject)
}

// 远程查询树
const remoteTree = async (query: string, associateTree: string) => {
  console.log(query, associateTree)
}

// 检查角色权限
const checkRole = (roles: string[]) => {
  if (!roles || roles.length == 0) {
    return true
  }
  if (userStore.userInfo?.roleArr?.includes('root')) {
    return true
  }
  return roles.some(item => userStore.userInfo?.roleArr?.includes(item))
}

// 初始化
onMounted(async () => {
  // 获取模块信息
  if (route.query?.mid) {
    const res = await apiGetModuleInfo(route.query?.mid as string)
    if (res.code === 200) {
      moduleInfo.value = res.data || {}
      tableJson.value = JSON.parse(moduleInfo.value?.tableJson || '[]')
      btnJson.value = JSON.parse(moduleInfo.value?.btnJson || '[]')
      apiJson.value = JSON.parse(moduleInfo.value?.apiJson || '[]')
    }
  }
  // 初始化查询列表
  await fetchList()
})
</script>

<style scoped>
.app-container {
  padding: 0px;
}

.query-form {
  margin-bottom: 0px;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.dialog-footer {
  text-align: right;
}
</style>
